/* SPDX-License-Identifier: GPL-2.0 */
#ifndef _SEMINIX_KTHREAD_H
#define _SEMINIX_KTHREAD_H

#include <seminix/sched.h>
#include <seminix/err.h>

struct cpumask;

__printf(3, 4)
struct task_struct *__kthread_create(int (*threadfn)(void *data),
                       void *data, const char namefmt[], ...);

/*
 * 创建一个内核线程
 */
#define kthread_create(threadfn, data, namefmt, arg...) __kthread_create(threadfn, data, namefmt, ##arg)

struct task_struct *kthread_create_on_cpu(int (*threadfn)(void *data),
                      void *data, unsigned int cpu, const char *namefmt);

/*
 * 创建一个内核线程并且唤醒它
 */
#define kthread_run(threadfn, data, namefmt, ...)			   \
({									   \
    struct task_struct *__k						   \
        = kthread_create(threadfn, data, namefmt, ## __VA_ARGS__); \
    if (!IS_ERR(__k))						   \
        wake_up_process(__k);					   \
    __k;								   \
})

void free_kthread_struct(struct task_struct *k);
void kthread_bind(struct task_struct *k, unsigned int cpu);
void kthread_bind_mask(struct task_struct *k, const struct cpumask *mask);
int kthread_stop(struct task_struct *k);
bool kthread_should_stop(void);
bool kthread_should_park(void);
void *kthread_data(struct task_struct *k);
void *kthread_probe_data(struct task_struct *k);
int kthread_park(struct task_struct *k);
void kthread_unpark(struct task_struct *k);
void kthread_parkme(void);

int kthreadd(void *unused);
extern struct task_struct *kthreadd_task;

#endif /* _SEMINIX_KTHREAD_H */
